#include <iostream>
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string>
#include <strings.h>
#include <cstdio>
#include <errno.h>
#include <unistd.h>
using namespace std;

#define SIZE 1024

void Usage(string str)
{
    cout<<"/n/t"<<str<<"+[serverip]+[serverport]"<<endl;
}

struct ThreadData
{
    string serverip;//要ip
    int sockfd;
    struct sockaddr_in server;//服务器的结构体
};

void* recv_message(void* args)
{
    ThreadData* t=static_cast<ThreadData*>(args);

    char buffer[SIZE];
    while(true)
    {
        struct sockaddr_in temp;
        socklen_t len;

        ssize_t s=recvfrom(t->sockfd,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&temp,&len);//阻塞过程
        if(s<0) continue;

        buffer[s]=0;

        cout<<buffer<<endl;   //打印收到的消息
    }
}

void* send_message(void* args)
{
    ThreadData* t=static_cast<ThreadData*>(args);

    string welcome=t->serverip;
    welcome+="comming";//代表，运行客服端的用户，进入群聊

    sendto(t->sockfd,welcome.c_str(),welcome.size(),0,(struct sockaddr*)&(t->server),sizeof(t->server));

    string message;
    while(true)
    {
        cout<<"please enter"<<endl;
        getline(cin,message);
        sendto(t->sockfd,message.c_str(),message.size(),0,(struct sockaddr*)&(t->server),sizeof(t->server));
    }
}

int main(int agrc,char* agrv[])
{
    if(agrc!=3)
    {
        Usage(agrv[0]);
        exit(1);
    }
    struct ThreadData t;
    bzero(&t.server,sizeof(t.server));

    t.serverip=agrv[1];//获取ip

    t.server.sin_family=AF_INET;
    t.server.sin_port=htons((uint16_t)stoi(agrv[2])); //先转整形，再转网络序列

    t.server.sin_addr.s_addr=inet_addr(t.serverip.c_str());
    
    t.sockfd=socket(AF_INET,SOCK_DGRAM,0);

    if(t.sockfd<0)
    {
        perror("sockfd error");
        exit(1);
    }

    pthread_t server,client;

    pthread_create(&server,nullptr,recv_message,&t);
    pthread_create(&client,nullptr,send_message,&t);

    pthread_join(server,nullptr);
    pthread_join(client,nullptr);

    close(t.sockfd);

    return 0;
}